using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Unity.VisualScripting;

namespace NuoYan.Extension
{
    [Serializable]
    public struct SerializableKeyValuePair<TKey, TValue>
    {
        public TKey Key;
        public TValue Value;

        public SerializableKeyValuePair(TKey key, TValue value)
        {
            Key = key;
            Value = value;
        }
        // 显式转换：KeyValuePair<T,V> -> KV<T,V>
        public static explicit operator SerializableKeyValuePair<TKey, TValue>(KeyValuePair<TKey, TValue> kvp)
        {
            return new SerializableKeyValuePair<TKey, TValue>(kvp.Key, kvp.Value);
        }

        // 显式转换：KV<T,V> -> KeyValuePair<T,V>
        public static explicit operator KeyValuePair<TKey, TValue>(SerializableKeyValuePair<TKey, TValue> kv)
        {
            return new KeyValuePair<TKey, TValue>(kv.Key, kv.Value);
        }

        // 隐式转换：KeyValuePair<T,V> -> KV<T,V>
        public static implicit operator SerializableKeyValuePair<TKey, TValue>((TKey key, TValue value) tuple)
        {
            return new SerializableKeyValuePair<TKey, TValue>(tuple.key, tuple.value);
        }

        // 隐式转换：KV<T,V> -> (T key, V value)
        public static implicit operator (TKey key, TValue value)(SerializableKeyValuePair<TKey, TValue> kv)
        {
            return (kv.Key, kv.Value);
        }
    }

    /// <summary>
    /// 双向字典的Json转换器，解决序列化/反序列化问题
    /// </summary>
    public class BidirectionalDictionaryConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType.IsGenericType &&
                   objectType.GetGenericTypeDefinition() == typeof(BidirectionalDictionary<,>);
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            // 处理null值情况：如果JSON中该字段是null，直接返回空实例或null
            if (reader.TokenType == JsonToken.Null)
            {
                // 如果需要允许null，返回null；否则返回空实例
                return Activator.CreateInstance(objectType); // 这里返回空实例更安全
            }

            // 处理正常对象情况
            JToken token = JToken.Load(reader);
            if (token.Type != JTokenType.Object)
            {
                // 如果不是对象类型（比如数组或原始值），返回空实例
                return Activator.CreateInstance(objectType);
            }

            JObject jObject = (JObject)token;
            var dictionary = Activator.CreateInstance(objectType);

            // 获取_entries字段并反序列化
            var entriesField = objectType.GetField("_entries",
                BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);

            if (entriesField != null)
            {
                var entriesToken = jObject["_entries"];
                if (entriesToken != null && entriesToken.Type != JTokenType.Null)
                {
                    // 反序列化_entries列表（如果JSON中_entries为null，不赋值，保留默认空列表）
                    var entriesList = entriesToken.ToObject(entriesField.FieldType, serializer);
                    entriesField.SetValue(dictionary, entriesList);
                }
                // 如果JSON中_entries为null，保持原有默认的空列表（避免后续空引用）
            }

            // 手动调用OnAfterDeserialize初始化映射
            var onAfterDeserializeMethod = objectType.GetMethod("OnAfterDeserialize",
                BindingFlags.Public | BindingFlags.Instance);
            onAfterDeserializeMethod?.Invoke(dictionary, null);

            return dictionary;
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value == null)
            {
                // 如果对象为null，直接序列化null
                writer.WriteNull();
                return;
            }

            Type objectType = value.GetType();
            // 只序列化_entries字段
            var entriesField = objectType.GetField("_entries",
                BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);

            if (entriesField != null)
            {
                var entries = entriesField.GetValue(value);
                writer.WriteStartObject();
                writer.WritePropertyName("_entries");
                serializer.Serialize(writer, entries);
                writer.WriteEndObject();
            }
            else
            {
                writer.WriteNull();
            }
        }
    }

    /// <summary>
    /// 双向字典，可以同时通过key和value来查找
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TValue"></typeparam>
    [Serializable]
    [JsonConverter(typeof(BidirectionalDictionaryConverter))]
    public class BidirectionalDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>, ISerializationCallbackReceiver
    {
        [SerializeField]
        public List<SerializableKeyValuePair<TKey, TValue>> _entries = new List<SerializableKeyValuePair<TKey, TValue>>();

        [NonSerialized]
        private Dictionary<TKey, TValue> keyToValueMap = new Dictionary<TKey, TValue>();

        [NonSerialized]
        private Dictionary<TValue, TKey> valueToKeyMap = new Dictionary<TValue, TKey>();

        public BidirectionalDictionary() { }

        public BidirectionalDictionary(IDictionary<TKey, TValue> dictionary)
        {
            foreach (var item in dictionary)
            {
                Add(item.Key, item.Value);
            }
        }

        public void Add(TKey key, TValue value)
        {
            if (keyToValueMap.ContainsKey(key))
                throw new ArgumentException("字典中已经存在相同的key");
            if (valueToKeyMap.ContainsKey(value))
                throw new ArgumentException("字典中已经存在相同的value");

            _entries.Add(new SerializableKeyValuePair<TKey, TValue>(key, value));
            keyToValueMap.Add(key, value);
            valueToKeyMap.Add(value, key);
        }

        public bool RemoveByKey(TKey key)
        {
            if (keyToValueMap.TryGetValue(key, out TValue value))
            {
                _entries.RemoveAll(e => EqualityComparer<TKey>.Default.Equals(e.Key, key));
                keyToValueMap.Remove(key);
                valueToKeyMap.Remove(value);
                return true;
            }
            return false;
        }

        public bool RemoveByValue(TValue value)
        {
            if (valueToKeyMap.TryGetValue(value, out TKey key))
            {
                _entries.RemoveAll(e => EqualityComparer<TValue>.Default.Equals(e.Value, value));
                valueToKeyMap.Remove(value);
                keyToValueMap.Remove(key);
                return true;
            }
            return false;
        }

        public void Clear()
        {
            _entries.Clear();
            keyToValueMap.Clear();
            valueToKeyMap.Clear();
        }

        public void OnBeforeSerialize() { }

        public void OnAfterDeserialize()
        {
            keyToValueMap.Clear();
            valueToKeyMap.Clear();

            foreach (var entry in _entries)
            {
                if (keyToValueMap.ContainsKey(entry.Key))
                    throw new ArgumentException($"重复的键: {entry.Key}");

                if (valueToKeyMap.ContainsKey(entry.Value))
                    throw new ArgumentException($"重复的值: {entry.Value}");

                keyToValueMap[entry.Key] = entry.Value;
                valueToKeyMap[entry.Value] = entry.Key;
            }
        }

        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            foreach (var entry in _entries)
                yield return new KeyValuePair<TKey, TValue>(entry.Key, entry.Value);
        }

        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

        public IEnumerable<TKey> Keys => keyToValueMap.Keys;

        public IEnumerable<TValue> Values => valueToKeyMap.Keys;

        public int Count => keyToValueMap.Count;

        public bool IsReadOnly => false;

        public TValue this[TKey key]
        {
            get => keyToValueMap[key];
            set
            {
                if (keyToValueMap.TryGetValue(key, out TValue oldValue))
                {
                    valueToKeyMap.Remove(oldValue);
                }

                if (valueToKeyMap.ContainsKey(value))
                {
                    throw new ArgumentException("新值已存在于字典中");
                }

                // 更新_entries列表
                var index = _entries.FindIndex(e => EqualityComparer<TKey>.Default.Equals(e.Key, key));
                if (index != -1)
                {
                    _entries[index] = new SerializableKeyValuePair<TKey, TValue>(key, value);
                }
                else
                {
                    _entries.Add(new SerializableKeyValuePair<TKey, TValue>(key, value));
                }

                keyToValueMap[key] = value;
                valueToKeyMap[value] = key;
            }
        }

        public bool ContainsKey(TKey key) => keyToValueMap.ContainsKey(key);

        public bool ContainsValue(TValue value) => valueToKeyMap.ContainsKey(value);

        public bool TryGetValue(TKey key, out TValue value) => keyToValueMap.TryGetValue(key, out value);

        public TValue GetValue(TKey key)
        {
            if (keyToValueMap.TryGetValue(key, out var value))
            {
                return value;
            }
            Debug.LogError($"找不到键{key}对应的value");
            return default;
        }

        public TKey GetKey(TValue value)
        {
            if (valueToKeyMap.TryGetValue(value, out var key))
            {
                return key;
            }
            Debug.LogError($"找不到值{value}对应的key");
            return default;
        }
    }
    public static class DictionaryExtension
    {
        /// <summary>
        /// 根据值获取键
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        public static bool TryGetKey<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TValue value, out TKey key)
        {
            foreach (var item in dictionary)
            {
                if (item.Value.Equals(value))
                {
                    key = item.Key;
                    return true;
                }
            }
            key = default(TKey);
            return false;
        }

        public static TKey GetKey<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TValue value)
        {
            if (dictionary.TryGetKey(value, out var key))
            {
                return key;
            }
            Debug.LogError($"找不到值{value}对应的key");
            return default;
        }
    }
}